//
//
//
//
//
// Socks4Proxy.C
//


#include "Socks4Proxy.h"
#include "BaseJob.h"
#include "LogManager.h"
#include "Socks4Util.h"

#include <netinet/in.h>
#include <sys/socket.h>
#include <arpa/inet.h>

Socks4Proxy::Socks4Proxy(jobId_t id,
		const std::string& jobName,
		 void* arg,
		 int clientFD)
: BaseJob(id, jobName, arg), _clientFD(clientFD), _serverFD(-1)
{
	memset(_szUid, 0, sizeof(_szUid));
}

Socks4Proxy::~Socks4Proxy()
{
	close(_clientFD);
}

void Socks4Proxy::TimerSvc(void)
{
	LOGTRACE("Timeup...");
}

void Socks4Proxy::Run()
{
	LOGTRACE("Socks4Proxy::Run");
	NixTimer::Interval(2000);
	NixTimer::Start();

	do
	{
		if(false == GetCmd())
		{
			LOGERROR("Error Socks4Proxy::GetCmd");
			break;
		}

		if(false == CrtSockPeer())
		{
			LOGERROR("Error Socks4Proxy::CrtSockPeer");
			break;
		}
		LOGTRACE("Socks4Proxy::CrtSockPeer success");

	}while(0);

	NixTimer::Stop();
}

bool Socks4Proxy::CrtSockPeer(void)
{
	_serverFD = socket(AF_INET,   SOCK_STREAM,   0);
	if(_serverFD == -1)
	{
		LOGERROR("Error create serverFD");
		return false;
	}

	struct sockaddr_in  servaddr;
	memset(&servaddr, 0, sizeof(servaddr));

	servaddr.sin_family = AF_INET;
	servaddr.sin_addr.s_addr = inet_addr("10.8.32.115");
	servaddr.sin_port = _port;

	if(connect(_serverFD, (struct sockaddr *)&servaddr, sizeof(struct sockaddr))  == -1)
	{
		LOGERROR2("Error connect to remote server, ", strerror(errno));
		close(_serverFD);
		_serverFD = -1;
		return false;
	}
	return true;
}

void Socks4Proxy::PrintAll(std::ostream& os)
{
	BaseJob::PrintAll(os);
	os << "clientFD: " 
		<< _clientFD
		<< "serverFD: "
		<< _serverFD
		<< std::endl;
}

//
//
// Audit the connection
bool Socks4Proxy::Audit()
{
	return true;
}

bool Socks4Proxy::GetCmd(void)
{
	char szCmd[256];
	memset(szCmd, 0, sizeof(szCmd));

	int nRet = read(_clientFD, szCmd, sizeof(szCmd));
	if(nRet <= 0)
	{
		LOGERROR2("recv error", strerror(errno));
		return false;
	}
	LOGTRACE2("Recv success: ", nRet);
	

	if(false == Socks4Util::ParseSocks4Cmd(szCmd,
				nRet,
				_version,
				_cmd,
				_port,
				_ip,
				_szUid))
	{
		LOGERROR("ParseSocks4Cmd return error");
		return false;
	}

	LOGTRACE("ParseSocks4Cmd success");

	if(false == Audit())
	{
		LOGWARN2("Failed audit. uid:", _szUid);
		LOGWARN2("Failed audit. IP:", _ip);
		LOGWARN2("Failed audit. Port:", _port);
		return false;
	}

	return true;
}
